#!/usr/bin/env bash

set -euo pipefail

SCRIPT_NAME="$(basename "$0")"
CONTAINER_NAME="3xui"
IMAGE_NAME="bigbugcc/3x-ui:latest"
CONTAINER_PORT="2053"
XUI_USERNAME="admin"
XUI_PASSWORD="admin"

log_info()  { echo "[INFO]  $*"; }
log_warn()  { echo "[WARN]  $*"; }
log_error() { echo "[ERROR] $*" 1>&2; }

require_root() {
    if [ "${EUID:-$(id -u)}" -ne 0 ]; then
        log_error "请以 root 身份运行：sudo $SCRIPT_NAME"
        exit 1
    fi
}

require_docker() {
    if ! command -v docker >/dev/null 2>&1; then
        log_error "未检测到 docker。请先安装 docker 再运行本脚本。"
        echo "常见安装命令：curl -fsSL https://get.docker.com | sh"
        exit 1
    fi
}

detect_system() {
    if [ -f /etc/synoinfo.conf ] && [ -d /var/packages ]; then
        echo "dsm"
    elif grep -q "ID=debian" /etc/os-release && ls /vol1* &>/dev/null; then
        echo "fnos"
    elif [ -f /etc/os-release ]; then
        echo "linux"
    else
        echo "unknown"
    fi
}

get_docker_dir() {
    local system_type="$1"
    local dir=""

    case "$system_type" in
        "dsm")
            dir="/volume1/docker"
            ;;
        "fnos")
            dir="/vol1/1000/docker"
            ;;
        *)
            # 检查常见Docker目录
            for test_dir in "/opt/docker" "/docker" "/app/docker" "/data/docker"; do
                if [ -w "$test_dir" ] 2>/dev/null; then
                    dir="$test_dir"
                    break
                fi
            done
            [ -z "$dir" ] && dir="/opt/docker"
            ;;
    esac

    mkdir -p "$dir" || {
        log_error "无法创建目录 $dir"
        return 1
    }
    echo "$dir"
}

get_local_ip() {
    local ip
    # 优先使用路由IP
    ip=$(ip route get 1 2>/dev/null | awk '{print $7; exit}')
    
    if [ -z "$ip" ]; then
        ip=$(hostname -I | awk '{print $1}' 2>/dev/null)
    fi
    
    if [ -z "$ip" ]; then
        ip="127.0.0.1"
    fi
    
    echo "$ip"
}

check_port() {
    local port="$1"
    if command -v ss >/dev/null 2>&1; then
        if ss -tuln | grep -q ":${port} "; then
            log_warn "端口 ${port} 已被占用"
            read -rp "是否继续? [y/N]: " ans
            case "${ans:-N}" in
                y|Y) return 0 ;;
                *) exit 1 ;;
            esac
        fi
    else
        if netstat -tuln 2>/dev/null | grep -q ":${port} "; then
            log_warn "端口 ${port} 已被占用"
            read -rp "是否继续? [y/N]: " ans
            case "${ans:-N}" in
                y|Y) return 0 ;;
                *) exit 1 ;;
            esac
        fi
    fi
    return 0
}

pull_docker_image() {
    log_info "正在拉取Docker镜像..."
    if ! docker pull "$IMAGE_NAME"; then
        log_error "拉取Docker镜像失败，请检查网络连接"
        return 1
    fi
}

wait_for_service() {
    local max_attempts=30
    local attempt=1
    local ip="${1:-127.0.0.1}"
    
    log_info "等待服务启动..."
    
    while [ $attempt -le $max_attempts ]; do
        if curl -s "http://${ip}:${CONTAINER_PORT}" &>/dev/null; then
            log_info "服务已启动"
            return 0
        fi
        log_info "尝试 ${attempt}/${max_attempts}..."
        sleep 2
        ((attempt++))
    done
    
    log_warn "服务启动超时，请手动检查服务状态"
    return 1
}

ensure_container_absent_or_replace() {
    if docker ps -a --format '{{.Names}}' | grep -qx "$CONTAINER_NAME"; then
        log_warn "容器 $CONTAINER_NAME 已存在。"
        read -rp "是否删除并继续安装? [y/N]: " ans
        case "${ans:-N}" in
            y|Y)
                docker rm -f "$CONTAINER_NAME" >/dev/null || true
                ;;
            *)
                log_error "已取消，退出。"
                exit 1
                ;;
        esac
    fi
}

run_container() {
    local base_dir="$1"
    local config_dir="${base_dir}/3xui"
    local cert_dir="${base_dir}/3xui/cert"
    
    mkdir -p "$config_dir" "$cert_dir" || {
        log_error "无法创建必要的目录"
        return 1
    }
    
    log_info "启动容器 $CONTAINER_NAME ..."
    
    docker run -d \
        --name "$CONTAINER_NAME" \
        --network=host \
        -v "${config_dir}:/etc/x-ui/" \
        -v "${cert_dir}:/root/cert/" \
        --restart=unless-stopped \
        "$IMAGE_NAME"
}

show_success_info() {
    local config_dir="$1"
    local cert_dir="$2"
    local ip=$(get_local_ip)
    
    echo
    log_info "3X-UI 安装成功！"
    echo "==========================================="
    echo "🌐  访问地址:   http://${ip}:${CONTAINER_PORT}"
    echo "🔌  容器端口:   ${CONTAINER_PORT}"
    echo "👤  默认用户名: ${XUI_USERNAME}"
    echo "🔑  默认密码:   ${XUI_PASSWORD}"
    echo "📁  配置目录:   ${config_dir}"
    echo "📄  证书目录:   ${cert_dir}"
    echo "📊  查看日志:   docker logs -f ${CONTAINER_NAME}"
    echo "⚡  重启服务:   docker restart ${CONTAINER_NAME}"
    echo "🛑  停止服务:   docker stop ${CONTAINER_NAME}"
    echo "🚀  启动服务:   docker start ${CONTAINER_NAME}"
    echo "==========================================="
    log_warn "请及时修改默认用户名和密码！"
    echo "==========================================="
}

show_system_info() {
    echo "系统信息:"
    echo "  OS: $(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '"' || uname -s)"
    echo "  内核: $(uname -r)"
    echo "  架构: $(uname -m)"
    echo "  Docker: $(docker --version 2>/dev/null | cut -d ',' -f 1 || echo "未安装")"
}

main() {
    require_root
    require_docker
    
    log_info "3X-UI 自动化安装脚本"
    echo "==========================================="
    
    show_system_info
    echo "==========================================="

    # 检测系统
    system_type=$(detect_system)
    case "$system_type" in
        "dsm") log_info "系统类型: 群辉DSM" ;;
        "fnos") log_info "系统类型: FNOS" ;;
        *) log_info "系统类型: 通用Linux" ;;
    esac

    # 获取目录
    dir=$(get_docker_dir "$system_type")
    log_info "使用目录: $dir"

    # 确认安装
    echo "==========================================="
    log_info "安装摘要:"
    echo "  容器名称: $CONTAINER_NAME"
    echo "  镜像版本: $IMAGE_NAME"
    echo "  数据目录: ${dir}/3xui"
    echo "  容器端口: $CONTAINER_PORT"
    echo "  网络模式: host"
    echo "==========================================="
    
    read -rp "是否继续安装? [y/N]: " ans
    case "${ans:-N}" in
        y|Y) ;;
        *)
            log_info "安装已取消"
            exit 0
            ;;
    esac

    # 检查端口
    check_port "$CONTAINER_PORT"

    # 拉取镜像
    pull_docker_image || exit 1

    # 清理旧容器
    ensure_container_absent_or_replace

    # 运行容器
    run_container "$dir" || {
        log_error "启动容器失败"
        exit 1
    }

    # 等待服务启动
    local ip=$(get_local_ip)
    wait_for_service "$ip"

    # 显示成功信息
    show_success_info "${dir}/3xui" "${dir}/3xui/cert"

    log_info "安装完成。"
}

main "$@"